// -*- C++ -*-

//=============================================================================
/**
*  @file    Service_Repository.h
*
*	@date    2009-12-18 14:53
*
*  @author wing <totti19851101@gmail.com>
*/
//=============================================================================

#ifndef _SERVICE_REPOSITORY_H_
#define _SERVICE_REPOSITORY_H_

#include "Pre.h"

class Service_Type;

/**
* @class Service_Repository
*
* @brief Contains all the services offered by a Service
* Configurator-based application.
*
* This class contains a vector of <Service_Types> *'s and
* allows an administrative entity to centrally manage and
* control the behavior of application services.  Note that if
* services are removed from the middle of the repository the
* order won't necessarily be maintained since the <remove>
* method performs compaction.  However, the common case is not
* to remove services, so typically they are deleted in the
* reverse order that they were added originally.
*/
class Service_Repository
{
public:
	friend class Service_Repository_Iterator;

	enum
	{
		DEFAULT_SIZE = 1024;
	};

	// = Initialization and termination methods
	/// Initialization the Repository
	Service_Repository(void);

	/// Initialization the Repository.
	Service_Repository( int size );

	/// Initialization the Repository.
	int open( int size = DEFAULT_SIZE );

	/// Close down the repository and free up dynamically allocated resources.
	~Service_Repository(void);
	
	/// Close down the repository and free up dynamically allocated resources.
	int close(void);

	/// Finalize all the services by calling <fini> and deleting
	/// dynamically allocated resources.
	int fini(void);

	/// Get pointer to a process-wide Service_Repository.
	static Service_Repository* instance( int size = Service_Repository::DEFAULT_SIZE );

	/// Set pointer to a process-wide Service_Repository and return
	/// existing pointer
	static Service_Repository* instance( Service_Repository* );

	/// Delete the dynamically allocated Singleton.
	static void close_singleton(void);

	// = Search structure operations (all acquire locks as necessary).

	/// Insert a new service record.  Returns -1 when the service repository is full
	/// and 0 on success.
	int insert (const Service_Type *);

	/**
	* Locate an entry with <name> in the table.  If <ignore_suspended>
	* is set then only consider services marked as resumed.  If the
	* caller wants the located entry, pass back a pointer to the
	* located entry via <srp>.  If <name> is not found, -1 is returned.
	* If <name> is found, but it is suspended and the caller wants to
	* ignore suspended services a -2 is returned.
	*/
	int find (const char name[],
		const Service_Type **srp = 0,
		int ignore_suspended = 1);

	/// Remove an existing service record. If @a sr == 0, the service record
	/// is deleted before control is returned to the caller. If @a sr != 0,
	/// the service's record is removed from the repository, but not deleted;
	/// *sr receives the service record pointer and the caller is responsible
	/// for properly disposing of it.
	int remove (const char[], Service_Type **sr = 0);

	// = Liveness control
	/// Resume a service record.
	int resume (const char[], const Service_Type ** = 0);

	/// Suspend a service record.
	int suspend (const char[], const Service_Type ** = 0);

	/// Return the current size of the repository.
	int current_size (void) const;

	/// Return the total size of the repository.
	int total_size (void) const;

	/// Dump the state of an object.
	void dump (void) const;

private:
	/// Locates <service_name>.  Must be called without locks being
	/// held...
	int find_i (const char service_name[],
		const Service_Type ** = 0,
		int ignore_suspended = 1);

	/// Contains all the configured services.
	const Service_Type **service_vector_;

	/// Current number of services.
	int current_size_;

	/// Maximum number of services.
	int total_size_;

	/// Pointer to a process-wide Service_Repository.
	static Service_Repository *svc_rep_;

	/// Must delete the <svc_rep_> if non-0.
	static int delete_svc_rep_;
};

/**
* @class Service_Repository_Iterator
*
* @brief Iterate through the Service_Repository.
*
* Make sure not to delete entries as the iteration is going on
* since this class is not designed as a robust iterator.
*/
class Service_Repository_Iterator
{
public:
	// = Initialization and termination methods.
	/// Constructor initializes the iterator.
	Service_Repository_Iterator (Service_Repository &sr,
		int ignored_suspended = 1);

	/// Destructor.
	~Service_Repository_Iterator (void);

	// = Iteration methods.

	/// Pass back the <next_item> that hasn't been seen in the repository.
	/// Returns 0 when all items have been seen, else 1.
	int next (const Service_Type *&next_item);

	/// Returns 1 when all items have been seen, else 0.
	int done (void) const;

	/// Move forward by one element in the repository.  Returns 0 when all the
	/// items in the set have been seen, else 1.
	int advance (void);

	/// Dump the state of an object.
	void dump (void) const;

private:
	/// Reference to the Service Repository we are iterating over.
	Service_Repository &svc_rep_;

	/// Next index location that we haven't yet seen.
	int next_;

	/// Are we ignoring suspended services?
	int ignore_suspended_;
};

#include "Post.h"
#endif//_SERVICE_REPOSITORY_H_